/*
 * Copyright (c) 2011 Obix Labs Limited
 * Redistribution and use in source and binary forms, 
 * with or without modification, are permitted provided 
 * that the following conditions are met:
 * 
 * 		Redistribution of source code must retain the above 
 * 		copyright notice, this list of conditions and the 
 * 		following disclaimer.
 *
 * 		Redistribution in binary form must reproduce the 
 * 		above copyright notice, this list of conditions 
 * 		and the following disclaimer in the documentation 
 * 		and/or other materials provided with the distribution.
 * 
 * 	THIS SOFTWARE IS PROVIDED "AS IS," WITHOUT A WARRANTY OF 
 * 	ANY KIND. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS 
 * 	AND WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, 
 * 	FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, 
 * 	ARE HEREBY EXCLUDED. OBIX LABS LIMITED ("Obix Labs") AND ITS 
 * 	LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE 
 * 	AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR 
 * 	ITS DERIVATIVES. IN NO EVENT WILL Obix Labs OR ITS LICENSORS BE 
 * 	LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, 
 * 	INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE 
 * 	DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF 
 * 	LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS 
 * 	SOFTWARE, EVEN IF Obix Labs HAS BEEN ADVISED OF THE POSSIBILITY OF 
 * 	SUCH DAMAGES.
 */
package com.obixlabs.commons.zip;

import java.util.Collection;
import java.util.LinkedHashMap;

import com.obixlabs.commons.util.SimpleHashCodeCalculator;

/**
 * <p>
 * Represents a folder in a compressed archive. A folder is capable
 * of holding other folders as well as {@link CompressedData 
 * unary files/items}. 
 * </p>
 */
public class CompressedDataFolder extends CompressedItem
{
	private static final long serialVersionUID = 4244101344819753249L;
	
	/**
	 * <p>
	 * The folder's contents.
	 * </p>
	 */
	private LinkedHashMap<String,CompressedItem> children;
	
	/**
	 * <p>
	 * Constructs an instance with the given name.
	 * </p>
	 * 
	 * @param name The folder's name.
	 */
	public CompressedDataFolder(String name)
	{ 
		super(name);
		children = new LinkedHashMap<String,CompressedItem>(); 
	}
	
	
	/**
	 * <p>
	 * Returns a read-only collection containing 
	 * all of the folder's children. The 
	 * {@link #isFolder(CompressedItem)}
	 * method can be used to test if a given 
	 * element in the list is a folder or {@link CompressedItem 
	 * a unary file}.
	 * </p>
	 * 
	 * @return A read-only collection of the 
	 * folder's children.
	 */
	public Collection<CompressedItem> getChildren() 
	{return children.values();}		
	
	/**
	 * <p>
	 * Returns the number of children contained 
	 * in the folder.
	 * </p>
	 * 
	 * @return	The number of {@link CompressedItem 
	 * items} contained in the folder. 
	 */
	public int size() { return children.size();}

	/**
	 * <p>
	 * Adds the given item to this folder, thereby 
	 * {@link #setParent(CompressedDataFolder) setting up 
	 * a parent/child relationship between 
	 * this folder and the given item}.  
	 * </p>
	 * 
	 * @param item	The child item to add to the folder.
	 * @return	<code>True</code> if this folder did not 
	 * already contain an item with the given name, and
	 * <code>false</code> if the folder already contains
	 * an item with the same name which is overwritten 
	 * by this call.
	 */
	public boolean add(CompressedItem item) 
	{
		boolean result = false;
		if (children.put(item.getName(),item)==null)
			result = true;
		item.setParent(this);
		return result;
	}
	
	@Override
	public int hashCode()
	{		
		return SimpleHashCodeCalculator.calculateFromFields(
																		getName(), children);
	}

	@Override
	public boolean equals(Object obj)
	{
		boolean result = false;
		
		if (this == obj) result = true;
		else if (obj instanceof CompressedDataFolder)
		{
			CompressedDataFolder other = (CompressedDataFolder) obj;
			
			if (children.equals(other.children) && super.equals(other)) 
				result = true;
		}		
		return result;
	}

	/**
	 * <p>
	 * Returns the {@link #add(CompressedItem) child item} with
	 * the given name. 
	 * </p>
	 * 
	 * @param name	The name of the {@link CompressedItem item}
	 * to return.
	 * 
	 * @return	The {@link #add(CompressedItem) child item} with
	 * the given name, if such a child was {@link #add(CompressedItem)
	 * previously added to the folder}, and <code>null</code> otherwise.
	 */
	public CompressedItem get(String name) { return children.get(name); }
}